package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.DataManager;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.rooms.absrooms.AbsChessRoom;
import com.myk.game.gobangchess.signs.ColorSign;
import com.myk.game.gobangchess.signs.GroundSign;
import com.myk.game.gobangchess.signs.TextSign;

import java.util.ArrayList;
import java.util.List;

/**
 * 简单公主骑士棋old备份
 */
public class PrincessKnightChessRoom extends AbsChessRoom {

    private List<Human> humanList; //场上角色集合
    private Human choose; //当前选中的角色

    public PrincessKnightChessRoom(String roomName) {
        super(roomName, "\t\t\t\t一款非常简单的杀王棋，三种棋子骑士不能吃公主，公主只能吃骑士，强盗不能吃骑士，棋子不能越过或走到墙上，公主走到对方底线或者吃掉对方公主获胜。", "公主骑士棋", BoardStyleData.PRINCES_KNIGHT_CHESS_STYLE, true, false);
    }

    @Override
    protected void doStart() {
        DataManager.noticeAllGameStart(player_black, player_white, roomName);
        overFlag = 1;//重置结束状态：对弈进行中未结束
        playingStartTime = System.currentTimeMillis(); //重置对弈开始时间
        resetGrids();
        initHumanList(); //游戏开始的时候初始化棋子和布局
        noticeBlackMove();
        preHistory(); //准备记录日志
    }

    @Override
    public void resetGrids() {
        step = 0;
        gameTip = "-1";
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        humanList = null;
    }

    @Override
    public String getRuleText() {
        return null;
    }

    @Override
    public String getGameInfo() {
        //先全部初始化
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        //根据humanList集合和choose对象来生成要显示到客户端的布局和标记
        if (humanList != null && humanList.size() > 0) {
            for (Human human : humanList) {
                if (!human.isDie) {
                    curGrids[human.pRow][human.pCol] = human.mSide; //显示棋子的底座
                    signList.add(new TextSign(getIndex(human.pRow, human.pCol), human.mName, human.getColor())); //显示棋子的文字
                }
            }
            if (choose != null && !choose.isDie) { //棋子被选中状态时
                signList.add(new GroundSign(getIndex(choose.pRow, choose.pCol), "#00FFFFFF", "#DD33AA33", 1.3F, 0, 1));
                List<int[]> canMovedPosList = choose.getCanMovedPos(curGrids, humanList); //获取该棋子可移动到的格子的坐标集合
                if (canMovedPosList != null && canMovedPosList.size() > 0) {
                    List<Integer> ids = new ArrayList<>();
                    for (int[] canMovedPos : canMovedPosList) {
                        ids.add(getIndex(canMovedPos[0], canMovedPos[1]));
                    }
                    signList.add(new ColorSign(ids, "#AA33AA33")); //可移动到的格子用更淡的绿色表示
                }
            }
        }
        return super.getGameInfo();
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (value == 1) { //黑方点击
            if (choose == null || choose.mSide != 1) { //如果目前没有选中的黑方单位
                Human human = getHumanByPos(row, col);
                if (human != null && human.mSide == 1) {
                    choose = human; //选中己方棋子
                    noticeAllRefreshGameInfo(); //仅仅刷新显示，黑方还能继续点击
                }
            }
            else { //如果已经有选中的黑方单位
                if (choose.isPosCanMove(row, col, curGrids, humanList)) { //黑方点击的位置属于选中棋子的可移动范围
                    if (step == 0 && !(choose instanceof Knight)) {
                        noticeAllBroadcast("先手第一步只能走骑士");
                        return;
                    }
                    Human other = getHumanByPos(row, col); //这里若能拿到棋子肯定是对方的
                    choose.pRow = row; //实际移动行为
                    choose.pCol = col; //实际移动行为
                    stepAdd();
                    ;

                    if (other != null) { //吃子判定
                        other.isDie = true;
                        humanList.remove(other);
                        if (other instanceof Princess) { //如果吃掉了对面的公主直接获胜
                            choose = null;
                            doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑吃掉了白方的公主获胜！");
                        }
                        else {
                            choose = null;
                            noticeWhiteMove();
                        }
                    }
                    else { //移子判定
                        if (choose instanceof Princess && choose.pRow == curGrids.length - 1) { //如果黑方公主进入了白方的底线
                            choose = null;
                            doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑将公主走进白方底线获胜！");
                        }
                        else { //换对方行动
                            choose = null;
                            noticeWhiteMove();
                        }
                    }
                }
                else { //点击了不可移动的位置时
                    Human human = getHumanByPos(row, col);
                    if (human != null && human.mSide == 1) {
                        choose = human; //切换选中己方棋子
                        noticeAllRefreshGameInfo(); //仅仅刷新显示，黑方还能继续点击
                    }
                    else {
                        choose = null; //点击了其它地方则关闭可移动路径的标记
                        noticeAllRefreshGameInfo(); //仅仅刷新显示，黑方还能继续点击
                    }
                }
            }
        }
        else if (value == 2) { //白方点击
            if (choose == null || choose.mSide != 2) {//如果目前没有选中的白方单位
                Human human = getHumanByPos(row, col);
                if (human != null && human.mSide == 2) {
                    choose = human;
                    noticeAllRefreshGameInfo();
                }
            }
            else {
                if (choose.isPosCanMove(row, col, curGrids, humanList)) { //点击的位置属于选中棋子的可移动范围
                    if (step == 0 && !(choose instanceof Knight)) {
                        noticeAllBroadcast("先手第一步只能走骑士");
                        return;
                    }
                    Human other = getHumanByPos(row, col);//这里若能拿到棋子肯定是对方的
                    choose.pRow = row; //实际移动行为
                    choose.pCol = col; //实际移动行为
                    stepAdd();
                    ;
                    if (other != null) { //吃子判定
                        other.isDie = true;
                        humanList.remove(other);
                        if (other instanceof Princess) { //如果吃掉了对面的公主直接获胜
                            choose = null;
                            doOver(WinMode.WHITE_WIN, player_black.getNickNameOrTemp() + "执白吃掉了黑方的公主获胜！");
                        }
                        else {
                            choose = null;
                            noticeBlackMove();
                        }
                    }
                    else { //移子判定
                        if (choose instanceof Princess && choose.pRow == 0) { //如果白方公主进入了黑方的底线
                            choose = null;
                            doOver(WinMode.WHITE_WIN, player_black.getNickNameOrTemp() + "执白将公主走进黑方底线获胜！");
                        }
                        else { //换对方行动
                            choose = null;
                            noticeBlackMove();
                        }
                    }
                }
                else {
                    Human human = getHumanByPos(row, col);
                    if (human != null && human.mSide == 2) {
                        choose = human; //切换选中己方棋子
                        noticeAllRefreshGameInfo(); //仅仅刷新显示，还能继续点击
                    }
                    else {
                        choose = null;
                        noticeAllRefreshGameInfo(); //仅仅刷新显示，白方还能继续点击
                    }
                }
            }
        }
    }

    private Human getHumanByPos(int row, int col) {
        for (Human human : humanList) {
            if (!human.isDie && human.pRow == row && human.pCol == col) {
                return human;
            }
        }
        return null;
    }

    //初始化棋子和棋子布局
    private void initHumanList() {
        humanList = new ArrayList<>();
        humanList.add(new Knight(1, 0, 0));
        humanList.add(new Robber(1, 0, 1));
        humanList.add(new Princess(1, 1, 2));
        humanList.add(new Robber(1, 0, 3));
        humanList.add(new Knight(1, 0, 4));
        humanList.add(new Knight(2, 6, 0));
        humanList.add(new Robber(2, 6, 1));
        humanList.add(new Princess(2, 5, 2));
        humanList.add(new Robber(2, 6, 3));
        humanList.add(new Knight(2, 6, 4));
        choose = null;
    }


    /**
     * 角色基类
     */
    private abstract static class Human {
        String mName; //棋子简名
        int mSide; //归属黑棋还是白棋
        int pRow; //在棋盘上的横坐标
        int pCol; //在棋盘上的纵坐标
        boolean isDie; //棋子是否死亡？

        public Human(String name, int mSide, int pRow, int pCol) {
            this.mName = name;
            this.mSide = mSide;
            this.pRow = pRow;
            this.pCol = pCol;
            this.isDie = false;
        }

        public String getColor() {
            if (mSide == 1) {
                return "#FFAA3333";
            }
            else {
                return "#FF3333AA";
            }
        }

        public List<int[]> getCanMovedPos(int[][] curGrids, List<Human> humanList) {
            List<int[]> canMovedPosList = new ArrayList<>();
            int h = curGrids.length;
            int w = curGrids[0].length;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    if (isPosCanMove(i, j, curGrids, humanList)) {
                        canMovedPosList.add(new int[]{i, j});
                    }
                }
            }
            return canMovedPosList;
        }

        public abstract boolean isPosCanMove(int row, int col, int[][] curGrids, List<Human> humanList);

        public abstract boolean isStrongerThan(Human other);
    }

    /**
     * 骑士
     */
    private static class Knight extends Human {

        public Knight(int mSide, int pRow, int pCol) {
            super("骑", mSide, pRow, pCol);
        }

        @Override
        public boolean isPosCanMove(int row, int col, int[][] curGrids, List<Human> humanList) {
            if (GridsUtils.isInGrids(curGrids, row, col)) {//所选坐标在格子中

                if (row != pRow && col != pCol) { //骑士的移动距离为直向无限格
                    return false;
                }
                else { //骑士不能越过墙也不能越过其它棋子
                    if (row == pRow) {
                        if (col > pCol) {
                            for (int i = 1; i < col - pCol; i++) {
                                if (curGrids[row][pCol + i] != 0) {
                                    return false; //路径上有墙或者有其它棋子
                                }
                            }
                        }
                        else if (col < pCol) {
                            for (int i = 1; i < pCol - col; i++) {
                                if (curGrids[row][col + i] != 0) {
                                    return false; //路径上有墙或者有其它棋子
                                }
                            }
                        }
                    }
                    if (col == pCol) {
                        if (row > pRow) {
                            for (int i = 1; i < row - pRow; i++) {
                                if (curGrids[pRow + i][col] != 0) {
                                    return false; //路径上有墙
                                }
                            }
                        }
                        else if (row < pRow) {
                            for (int i = 1; i < pRow - row; i++) {
                                if (curGrids[row + i][col] != 0) {
                                    return false; //路径上有墙
                                }
                            }
                        }
                    }
                }

                if (curGrids[row][col] == 0) { //所选位置时空地时
                    return true;
                }
                else if (curGrids[row][col] == 9) { //所选位置是墙
                    return false;
                }
                else if (curGrids[row][col] == mSide) { //所选位置是自己方棋子
                    return false;
                }
                else { //所选位置是对方棋子
                    for (Human human : humanList) {
                        if (human.mSide != mSide) {
                            if (human.pRow == row && human.pCol == col) {
                                if (isStrongerThan(human)) { //能够吃对方棋子时
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            return false;
        }

        @Override
        public boolean isStrongerThan(Human other) {
            return !(other instanceof Princess); //除了公主骑士谁都能吃
        }
    }

    /**
     * 公主
     */
    private static class Princess extends Human {

        public Princess(int mSide, int pRow, int pCol) {
            super("主", mSide, pRow, pCol);
        }

        @Override
        public boolean isPosCanMove(int row, int col, int[][] curGrids, List<Human> humanList) {
            if (GridsUtils.isInGrids(curGrids, row, col)) {//所选坐标在格子中

                if (Math.abs(row - pRow) != 1 || Math.abs(col - pCol) != 1) { //公主的移动步伐为斜着8方向走1格
                    return false;
                }

                if (curGrids[row][col] == 0) {
                    return true;
                }
                else if (curGrids[row][col] == 9) { //所选位置是墙
                    return false;
                }
                else if (curGrids[row][col] == mSide) { //所选位置是原位置
                    return false;
                }
                else { //所选位置是对方棋子
                    for (Human human : humanList) {
                        if (human.mSide != mSide) {
                            if (human.pRow == row && human.pCol == col) {
                                if (isStrongerThan(human)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            return false;
        }

        @Override
        public boolean isStrongerThan(Human other) {
            return other instanceof Knight; //公主仅能吃骑士
        }
    }

    /**
     * 强盗
     */
    private static class Robber extends Human {

        public Robber(int mSide, int pRow, int pCol) {
            super("盗", mSide, pRow, pCol);
        }

        @Override
        public boolean isPosCanMove(int row, int col, int[][] curGrids, List<Human> humanList) {
            if (GridsUtils.isInGrids(curGrids, row, col)) {//所选坐标在格子中

                if (Math.abs(row - pRow) > 1 || Math.abs(col - pCol) > 1) { //强盗的移动距离为8方向1格
                    return false;
                }

                if (curGrids[row][col] == 0) {
                    return true;
                }
                else if (curGrids[row][col] == 9) { //所选位置是墙
                    return false;
                }
                else if (curGrids[row][col] == mSide) { //所选位置是原位置
                    return false;
                }
                else { //所选位置是对方棋子
                    for (Human human : humanList) {
                        if (human.mSide != mSide) {
                            if (human.pRow == row && human.pCol == col) {
                                if (isStrongerThan(human)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            return false;
        }

        @Override
        public boolean isStrongerThan(Human other) {
            return !(other instanceof Knight); //除了骑士强盗谁都能吃
        }
    }
}
